home *** CD-ROM | disk | FTP | other *** search
- /*
- File: serialbox.c
-
- Contains: Code for serial box driver
-
- Version: xxx put version here xxx
-
- Copyright: © 1998 by Apple Computer, Inc., all rights reserved.
-
- */
-
-
-
- #define PBVERSION1 1
- #include <USB.h>
-
- #include "DriverServices.h"
- #include "processes.h"
- #include "ShimSerialInternal.h"
- #include "SerialBox.h"
-
-
- enum{
- kSerBoxSetBaudRate = 0,
- kSerBoxSetStopBits = 1,
- kSerBoxSetDataBits = 2,
- kSerBoxSetParity = 3,
- kSerBoxSetDTRState = 0xa,
- kSerBoxSetRTSState = 0xb,
- kSerBoxSetBreakState = 0xc,
- kSerBoxSetControl = 0x10,
- kSerBoxSetParChar = 0x11,
- kSerBoxSetSerNum = 0x20,
- kSerBoxSetStrings = 0x21,
- kSerBoxGetCaps = 0x80,
- kAvailableStatus = 'okok'
- };
-
-
- typedef struct{
- USBPB pb;
- UInt8 *errorString;
- USBConfigurationDescriptor *conf;
- USBInterfaceDescriptor *interface;
- UInt32 interfaceOffset;
- USBDeviceRef deviceRef;
- USBPipeRef bulkIn;
- USBPipeRef bulkOut;
- USBPipeRef interrupt;
- USBDeviceDescriptorPtr deviceDescriptor;
- UInt8 modemStatus;
- UInt8 lineStatus;
- UInt8 onError;
- UInt8 retries;
- }serBoxPB;
-
- static serBoxPB gSerialGlobals;
- static USBPB syncPB, interruptPB, readPB, writePB;
-
-
- #if 1
-
- /* Incorporate debugging strings */
- #define noteError(s) sp->errorString = s;
-
- #else
-
- /* eliminate Error strings */
- #define noteError(s)
-
- #endif
-
-
- void serialBoxEntry(USBDeviceRef device, USBDeviceDescriptor *desc);
- static void StartStatusMonitor(USBPipeRef interruptPipe);
- static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler);
- void USBStartReadPolling(void);
-
- static Boolean immediateError(OSStatus err)
- {
- return((err != kUSBPending) && (err != noErr) );
- }
-
-
- #define buffsize 30
-
-
- static void ConfigurationHandler(USBPB *pb)
- {
- serBoxPB *sp = &gSerialGlobals;
- USBEndPointDescriptor *eDesc;
- static unsigned char *aString = "\pA test String";
- static unsigned char buffer[buffsize];
- OSStatus err;
-
- if(pb->usbStatus != noErr)
- {
- if( (sp->onError == 0) && (sp->retries > 0) )
- {
- /* no idea what to do now?? */
- USBExpertFatalError(sp->deviceRef, pb->usbStatus, sp->errorString, 1);
-
- /* Mark port as errored */
- }
- else
- {
- USBExpertStatus(sp->deviceRef, sp->errorString, 2);
- pb->usbRefcon = sp->onError;
-
- /* we'll delay coming back to here */
- sp->retries--;
-
- pb->usbReqCount = 0;
- /* pb->usbFlags = kUSBtaskTime */
- USBDelay(pb);
-
- }
-
- return;
- }
-
- sp->onError = 0;
-
- // USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialBox: Entering this state", pb->usbRefcon);
-
- do{switch(pb->usbRefcon++)
- {
-
- case 1:
- noteError("\pSerialBox driver does not recognize device (we'll try config 1 anyway)");
- if(sp->deviceDescriptor->numConf != 1)
- {
- USBExpertFatalError(sp->deviceRef, kUSBUnknownDeviceErr, sp->errorString, 0);
- // break; /* Now what ?? */
- }
-
- /* Configure device to single configuration */
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBDevice);
-
- pb->usbBRequest = kUSBRqSetConfig;
- pb->usbWValue = 1; /* Standard only (1st) configuration */
- // pb->usbWValue = 2; /* for USR Modem */
- pb->usbWIndex = 0;
- pb->usbReqCount = 0;
- pb->usbBuffer = nil;
- sp->onError = 1;
-
- noteError("\pSerial Driver Setting Config");
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
- break;
-
- case 2:
- /* get the full config descriptor */
- pb->pbVersion = kUSBCurrentPBVersion;
- sp->onError = 1;
- noteError("\pSerial Driver getting full config descriptor");
- if(immediateError(err = USBGetFullConfigurationDescriptor(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
- break;
-
- case 3:
- /* remember the full config descriptor */
- sp->conf = pb->usbBuffer;
-
- /* find the interface */
- pb->usbReqCount = 0;
- pb->usbValue1 = 0; /* any class */
- // pb->usbValue1 = kUSBDataClass; /* any class */
- pb->usbValue2 = 0; /* any subclass */
- pb->usbValue3 = 0; /* any protocol */
- pb->usbWValue = 0; /* alt */
- sp->onError = 1;
-
- noteError("\pSerial Driver parsing the interface");
- if(immediateError(err = USBFindNextInterfaceDescriptorImmediate(pb)))
- { /* this should return immediately */
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
- /* remember the current position */
- sp->interface = pb->usbBuffer;
- sp->interfaceOffset = pb->usbReqCount;
-
- /* Find the out endpoint */
- pb->usbFlags = kUSBOut;
- pb->usbValue1 = kUSBBulk;
- pb->usbValue2 = 0; /* Find the first one */
-
- noteError("\pSerial Driver parsing the bulk out endpoint");
- if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
- { /* this should return immediately */
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
- /* Save away the device ref, it gets overwritten by the open */
- sp->deviceRef = pb->usbReference;
-
- pb->usbFlags = kUSBOut;
- /* The params are set up correctly so open it */
- //eDesc = pb->usbBuffer;
- //pb->usbValue = USBToHostWord(eDesc->maxPacketSize);
- // max packet size is now returned in usbValue
-
- noteError("\pSerial Driver opening bulk out pipe");
- if(immediateError(err = USBOpenPipe(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
-
- break;
-
- case 4:
- /* Out Endpoint is open */
-
- /* remember the ref */
- sp->bulkOut = pb->usbReference;
-
- /* Find the in endpoint */
-
- /* restore the device ref, it gets overwritten by the open */
- pb->usbReference = sp->deviceRef;
-
- /* set search back to just found interface */
- pb->usbBuffer = sp->interface;
- pb->usbReqCount = sp->interfaceOffset;
-
- pb->usbFlags = kUSBIn;
- pb->usbValue1 = kUSBBulk;
- pb->usbValue2 = 0; /* Find the first one */
- sp->onError = 1;
-
- noteError("\pSerial Driver parsing the bulk in endpoint");
- if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
- { /* this should return immediatly */
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
- pb->usbFlags = kUSBIn;
- /* The params are set up correctly so open it */
- eDesc = pb->usbBuffer;
- pb->usbValue3 = USBToHostWord(eDesc->maxPacketSize);
-
- noteError("\pSerial Driver opening bulk in pipe");
- if(immediateError(err = USBOpenPipe(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
-
- break;
-
- case 5:
- /* In Endpoint is open */
-
- /* remember the ref */
- sp->bulkIn = pb->usbReference;
-
- /* Find the interrupt endpoint */
-
- /* restore the device ref, it gets overwritten by the open */
- pb->usbReference = sp->deviceRef;
-
- /* set search back to just found interface */
- pb->usbBuffer = sp->interface;
- pb->usbReqCount = sp->interfaceOffset;
-
- pb->usbFlags = kUSBIn;
- pb->usbValue1 = kUSBInterrupt;
- pb->usbValue2 = 0; /* Find the first one */
- sp->onError = 1;
-
- noteError("\pSerial Driver parsing the interrupt in endpoint");
- if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
- { /* this should return immediatly */
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
- pb->usbFlags = kUSBIn;
- /* The params are set up correctly so open it */
- eDesc = pb->usbBuffer;
- pb->usbValue3 = USBToHostWord(eDesc->maxPacketSize);
-
- noteError("\pSerial Driver opening interrupt in pipe");
- if(immediateError(err = USBOpenPipe(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
- }
-
-
- break;
-
- case 6:
- /* Interrupt is open */
-
- /* remember the ref */
- sp->interrupt = pb->usbReference;
-
- StartStatusMonitor(sp->interrupt);
-
- // device is fully configured, ready for somebody to set the baud rate, etc.
- // and start reading/writing to the bulk endpoints
- syncPB.usbStatus = kAvailableStatus;
- USBExpertStatus(sp->deviceRef, "\pSerial Box configuration complete.", 0);
- break;
-
- default:
- noteError("\pInternal Error unused case in SerialBox handler");
- USBExpertFatalError(sp->deviceRef, kUSBInternalErr, sp->errorString, pb->usbRefcon);
- break;
- }
- break; /* only execute once, unless continue used */
- }while(1); /* so case can be reentered with a continue */
- }
-
- UInt32 statusData;
-
- static void ResetInterruptPB(USBPB *pb)
- {
- pb->usbReqCount = 4;
- pb->usbBuffer = &statusData;
- pb->usbStatus = noErr;
- }
-
- static void interruptCompletion(USBPB *pb)
- {
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (pb->usbStatus != noErr){
- USBClearPipeStallByReference(gSerialGlobals.interrupt);
- USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialDriver: interruptCompletion err, clearing stall", 0);
- } else {
- sp->modemStatus = statusData & 0x0FF;
- sp->lineStatus = (statusData >> 8) & 0x0FF;
- }
-
- ResetInterruptPB(pb);
-
- if(immediateError(err = USBIntRead(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pCouldn't queue interrupt read!", 0);
- }
-
- }
-
- static void StartStatusMonitor(USBPipeRef interruptPipe)
- {
- USBPB *pb = &interruptPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- InitializePB(pb, interruptPipe, interruptCompletion);
-
- ResetInterruptPB(pb);
-
- if(immediateError(err = USBIntRead(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pCouldn't start interrupt read!", 0);
- }
-
- }
-
-
- // Synchronous routines for setting UART parameters
-
- static void syncCompletion(USBPB *pb)
- {
- serBoxPB *sp = &gSerialGlobals;
-
- if (pb->usbStatus != noErr)
- USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pSerialDriver: syncCompletion err for bRequest", pb->usbBRequest);
-
- pb->usbStatus = kAvailableStatus;
- }
-
- Boolean TimeoutPreviousRequest(void)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- AbsoluteTime startTime;
- Duration elapsedTime;
-
- if (pb->usbStatus == kAvailableStatus)
- return(false);
-
- startTime = UpTime();
-
- while (pb->usbStatus != kAvailableStatus){
- elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
- if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000); // make sure it's in milliseconds
- if (elapsedTime > 100*durationMillisecond){
- USBExpertFatalError(sp->deviceRef, -1, "\pSerial Driver, device request timeout - aborting", 0);
- USBAbortPipeByReference(pb->usbReference);
- return(true);
- }
- }
- return (false);
- }
-
- void USBSetBaudRateDivisor(UInt16 divisor)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetBaudRate;
- pb->usbWValue = divisor;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Baud rate", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetParChar(UInt8 parChar)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetParChar;
- pb->usbWValue = parChar;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Baud rate", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetStopBits(UInt16 stopBits)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetStopBits;
- pb->usbWValue = stopBits;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting StopBits", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetDataBits(UInt16 dataBits)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetDataBits;
- pb->usbWValue = dataBits;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting dataBits", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetParityBits(UInt16 parityBits)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetParity;
- pb->usbWValue = parityBits;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting parity", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetControl(UInt16 state)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetControl;
- pb->usbWValue = state;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Control", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
-
- void USBSetDTRState(Boolean state)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetDTRState;
- pb->usbWValue = state;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting DTR State", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetRTSState(Boolean state)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetRTSState;
- pb->usbWValue = state;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting RTS State", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- void USBSetBreakState(Boolean state)
- {
- USBPB *pb = &syncPB;
- serBoxPB *sp = &gSerialGlobals;
- OSStatus err;
-
- if (TimeoutPreviousRequest())
- return;
-
- pb->usbStatus = noErr;
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBVendor, kUSBDevice);
-
- pb->usbBRequest = kSerBoxSetBreakState;
- pb->usbWValue = state;
- pb->usbWIndex = 0; /* UART, we only have the one */
- pb->usbReqCount = 0;
-
- if(immediateError(err = USBDeviceRequest(pb)))
- {
- USBExpertFatalError(sp->deviceRef, err, "\pSerial Driver Setting Break State", 0);
- pb->usbStatus = kAvailableStatus;
- }
- }
- UInt32 USBGetModemStatus(void)
- {
- serBoxPB *sp = &gSerialGlobals;
-
- return(sp->modemStatus);
- }
-
- void serialBoxEntry(USBDeviceRef device, USBDeviceDescriptor *desc)
- {
- static Boolean beenThereDoneThat = false;
- static USBDeviceDescriptor ourDeviceDescriptor;
-
- if(beenThereDoneThat)
- {
- USBExpertFatalError(device, kUSBInternalErr, "\pSerial driver called second time", 0);
- return;
- }
- beenThereDoneThat = true;
-
- ourDeviceDescriptor = *desc;
- gSerialGlobals.deviceDescriptor = &ourDeviceDescriptor;
- gSerialGlobals.deviceRef = device;
-
- InitializePB(&syncPB, device, syncCompletion);
-
- InitializePB(&gSerialGlobals.pb, device, ConfigurationHandler);
- gSerialGlobals.pb.usbRefcon = 1;
- gSerialGlobals.pb.usbBuffer = nil;
-
- ConfigurationHandler(&gSerialGlobals.pb);
- }
-
-
- static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler)
- {
- pb->pbVersion = kUSBCurrentPBVersion;
- pb->pbLength = sizeof(*pb);
- pb->usbReference = ref;
- pb->usbCompletion = handler;
- pb->usbStatus = noErr;
-
- }
-
- void ShimInput(UInt8 *buf, UInt32 count)
- {
- IOParam * pb;
- OSErr result;
- register UInt16 nextIndex;
- register unsigned char rcvByte;
- unsigned char lineStatus;
- unsigned char newErrs;
- unsigned char cumErrs;
- ShimSerialGlobals * globals = gGlobals;
-
-
- // set return result to incomplete
-
- result = 1;
- cumErrs = 0;
-
- while(count--)
- {
- // pull out uart line status
-
- lineStatus = 0 /* gSerialGlobals.lineStatus */;
-
- // handle reading of data available in the uart receive buffer
-
- rcvByte = *buf++;
-
- // if software output flow control is enabled, check if this is an xon or xoff character
-
- if ( globals->serShk.fXOn &&
- (!(lineStatus & kRxErrMask)) &&
- ( (rcvByte == globals->serShk.xOn) ||
- (rcvByte == globals->serShk.xOff)))
- {
-
- // set software output flow control based on xon or xoff received
-
- globals->serStat.xOffHold = (rcvByte == globals->serShk.xOff);
- B_EnableOutput(globals);
- }
- else
- {
- // else this is to be treated as a data byte for the client
-
- // compute index into our input buffer
-
- nextIndex = globals->inBufEndIndex + 1;
- if ( nextIndex >= globals->inBufLen )
- nextIndex = 0;
-
- // stuff the character into the input buffer and update the index
-
- globals->inBufPtr[globals->inBufEndIndex] = rcvByte;
- globals->inBufEndIndex = nextIndex;
-
- // check for input buffer overflow
-
- if ( globals->inBufEndIndex == globals->inBufStartIndex )
- {
- // mark that we've had an overrun
-
- globals->serStat.cumErrs |= swOverrunErr;
- cumErrs |= swOverrunErr;
-
- // drop oldest character from our internal buffer
-
- globals->inBufStartIndex++;
- if ( globals->inBufStartIndex >= globals->inBufLen )
- globals->inBufStartIndex = 0;
-
- // we've had a software overrun -- rather than empty the uart
- // fifo and overwrite up to 16 bytes, we quit now and let the
- // client get a chance to read in the existing bytes -- if there
- // are still bytes pending in the fifo, we'll get interrupted
- // again real soon now...
- }
- }
-
- // check for receive error condition
- // for case of kRxStatusInterrupt with no data available
-
- if ( lineStatus & kRxErrMask )
- {
- // mark error
-
- newErrs = 0;
- if ( lineStatus & kParityErr ) newErrs |= parityErr;
- if ( lineStatus & kOverrunErr ) newErrs |= hwOverrunErr;
- if ( lineStatus & kFramingErr ) newErrs |= framingErr;
- if ( lineStatus & kBreakDetect ) newErrs |= breakErr;
- globals->serStat.cumErrs |= newErrs;
- cumErrs |= newErrs;
- }
-
- // check for an outstanding read request
-
- pb = (IOParam *)globals->pbIn;
- if (pb)
- {
- // copy bytes from input buffer into pb read buffer
- // (result is either 1=incomplete or 0=complete)
-
- result = B_FillReadRequest(globals, pb);
-
- // handle errors that cause read aborts
-
- if ( cumErrs & globals->serShk.errs )
- result = rcvrErr;
-
- // if we have fulfilled this read request, we
- // need to call IOCommandIsComplete and on it
- // and continue processing with the next request
-
- if ( result <= noErr )
- {
- globals->pbIn = nil;
- break;
- }
- }
-
-
- // handle hardware (dtr or rts) or software
- // (xon / xoff) input flow control as necessary
-
- B_InputFlowControl(globals);
-
- }
-
- // clean up after ourselves
- if (result <= noErr)
- ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceIn),result);
- }
-
- static errCount, readActive = false;
-
- void readCompletion(USBPB *pb)
- {
- if (pb->usbStatus == noErr){
- ShimInput(pb->usbBuffer, pb->usbActCount);
- }else{
- USBClearPipeStallByReference(gSerialGlobals.bulkIn);
- if (pb->usbActCount > 0)
- ShimInput(pb->usbBuffer, pb->usbActCount);
-
- if ((pb->usbStatus != kUSBUnderRunErr) && errCount++ < 10)
- USBExpertFatalError(gSerialGlobals.deviceRef, pb->usbStatus, "\pRead completion error, actCount", pb->usbActCount);
- }
- readActive = false;
- if (pb->usbStatus != kUSBAbortedError) // are we being asked to quit?
- USBStartReadPolling();
-
- }
-
- static UInt8 ioBuffer[64];
-
- void USBStartReadPolling()
- {
- OSStatus status;
-
- if (gSerialGlobals.bulkIn && !readActive){
- InitializePB(&readPB, gSerialGlobals.bulkIn, readCompletion);
- readPB.usbBuffer = ioBuffer;
- readPB.usbReqCount = sizeof(ioBuffer);
- if(immediateError(status = USBBulkRead(&readPB)))
- {
- USBExpertFatalError(gSerialGlobals.deviceRef, status, "\pSerial: Couldn't start read polling", 0);
- }
- readActive = true;
- }
- }
-
- void USBStopReadPolling()
- {
- USBExpertStatus(gSerialGlobals.deviceRef, "\pAborting Bulk-in pipe", 0);
-
- if (gSerialGlobals.bulkIn){
- USBAbortPipeByReference(gSerialGlobals.bulkIn);
- }
- }
-
-
- static UInt32 writeActive;
-
- void writeCompletion(USBPB *pb)
- {
- IOParam *iopb;
-
- writeActive--;
- if (pb->usbStatus != noErr) {
- USBClearPipeStallByReference(pb->usbReference);
- USBExpertFatalError(gSerialGlobals.deviceRef, pb->usbStatus, "\pWrite Failed", pb->usbActCount);
- }
-
- iopb = (IOParam *)pb->usbRefcon;
-
- iopb->ioActCount = pb->usbActCount;
-
- ShimSerialStubIODone((union ParamBlockRec *)iopb, *(gGlobals->dceOut), pb->usbStatus ? ioErr : 0);
-
- }
-
- OSStatus USBSerialWrite(IOParam *pb)
- {
- OSStatus status = noErr;
-
- if (writeActive){
- USBExpertFatalError(gSerialGlobals.deviceRef, writePB.usbStatus, "\pOverlapping writes!", pb->ioReqCount);
- status = ioErr;
- } else if (gSerialGlobals.bulkOut){
-
- InitializePB(&writePB, gSerialGlobals.bulkOut, writeCompletion);
- writePB.usbRefcon = (UInt32)pb;
- writePB.usbBuffer = pb->ioBuffer;
- writePB.usbReqCount = pb->ioReqCount;
- if(immediateError(status = USBBulkWrite(&writePB)))
- {
- USBExpertFatalError(gSerialGlobals.deviceRef, status, "\pSerial: Couldn't start write", 0);
- } else {
- writeActive++;
- status = 1;
- }
- } else {
- status = ioErr;
- }
- return (status);
- }
-
- void KillUSBIO(void)
- {
- IOParam * pb;
- ShimSerialGlobals * globals = gGlobals;
-
- USBExpertStatus(gSerialGlobals.deviceRef, "\pSerial Box: Killing all USB IO", 0);
-
- if (gSerialGlobals.bulkIn){
- USBAbortPipeByReference(gSerialGlobals.bulkIn);
- gSerialGlobals.bulkIn = nil;
- }
- if (gSerialGlobals.bulkOut){
- USBAbortPipeByReference(gSerialGlobals.bulkOut);
- gSerialGlobals.bulkOut = nil;
- }
- if (gSerialGlobals.interrupt){
- USBAbortPipeByReference(gSerialGlobals.interrupt);
- gSerialGlobals.interrupt = nil;
- }
-
- pb = (IOParam *)globals->pbIn;
- if (pb) {
- ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceIn),ioErr);
- }
- pb = (IOParam *)globals->pbOut;
- if (pb) {
- ShimSerialStubIODone((union ParamBlockRec *)pb,*(globals->dceOut),ioErr);
- }
- }
-
-
-